#include "test_common.hpp"
#include "tools/api.hpp"
#include <filesystem>
#include <fstream>
#include <thread>
#include <chrono>

namespace fs = std::filesystem;

void test_mkDir()
{
    std::string testDir = test_common::getTestTempDir() + "/test_mkdir";
    test_common::cleanupTestDir(testDir);
    
    bool result = MKDIR(testDir);
    ASSERT_TRUE(result);
    ASSERT_TRUE(fs::exists(testDir));
    ASSERT_TRUE(fs::is_directory(testDir));
    
    test_common::cleanupTestDir(testDir);
}

void test_rmDir()
{
    std::string testDir = test_common::getTestTempDir() + "/test_rmdir";
    test_common::cleanupTestDir(testDir);
    
    MKDIR(testDir);
    ASSERT_TRUE(fs::exists(testDir));
    
    bool result = RMDIR(testDir);
    ASSERT_TRUE(result);
    ASSERT_FALSE(fs::exists(testDir));
}

void test_touch()
{
    std::string testFile = test_common::getTestTempDir() + "/test_touch.txt";
    test_common::cleanupTestDir(fs::path(testFile).parent_path().string());
    
    bool result = TOUCH(testFile);
    ASSERT_TRUE(result);
    ASSERT_TRUE(fs::exists(testFile));
    ASSERT_TRUE(fs::is_regular_file(testFile));
    
    // 测试更新文件时间
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    auto time1 = fs::last_write_time(testFile);
    TOUCH(testFile);
    auto time2 = fs::last_write_time(testFile);
    ASSERT_TRUE(time2 >= time1);
    
    RM(testFile);
    test_common::cleanupTestDir(fs::path(testFile).parent_path().string());
}

void test_cpFile()
{
    std::string testDir = test_common::getTestTempDir();
    std::string sourceFile = testDir + "/source.txt";
    std::string targetFile = testDir + "/target.txt";
    test_common::cleanupTestDir(testDir);
    
    MKDIR(testDir);
    
    // 创建源文件
    {
        std::ofstream ofs(sourceFile);
        ofs << "test content";
        ofs.close();
    }
    
    bool result = CP(sourceFile, targetFile);
    ASSERT_TRUE(result);
    ASSERT_TRUE(fs::exists(targetFile));
    
    // 验证内容
    std::ifstream ifs(targetFile);
    std::string content;
    std::getline(ifs, content);
    ASSERT_STREQ("test content", content.c_str());
    
    test_common::cleanupTestDir(testDir);
}

void test_mvFile()
{
    std::string testDir = test_common::getTestTempDir();
    std::string sourceFile = testDir + "/source.txt";
    std::string targetFile = testDir + "/target.txt";
    test_common::cleanupTestDir(testDir);
    
    MKDIR(testDir);
    
    // 创建源文件
    {
        std::ofstream ofs(sourceFile);
        ofs << "test content";
        ofs.close();
    }
    
    bool result = MV(sourceFile, targetFile);
    ASSERT_TRUE(result);
    ASSERT_FALSE(fs::exists(sourceFile));
    ASSERT_TRUE(fs::exists(targetFile));
    
    test_common::cleanupTestDir(testDir);
}

void test_rmFile()
{
    std::string testDir = test_common::getTestTempDir();
    std::string testFile = testDir + "/test_rm.txt";
    test_common::cleanupTestDir(testDir);
    
    MKDIR(testDir);
    TOUCH(testFile);
    ASSERT_TRUE(fs::exists(testFile));
    
    bool result = RM(testFile);
    ASSERT_TRUE(result);
    ASSERT_FALSE(fs::exists(testFile));
    
    test_common::cleanupTestDir(testDir);
}

void test_list()
{
    std::string testDir = test_common::getTestTempDir();
    test_common::cleanupTestDir(testDir);
    
    MKDIR(testDir);
    TOUCH(testDir + "/file1.txt");
    TOUCH(testDir + "/file2.txt");
    MKDIR(testDir + "/subdir");
    
    std::vector<std::string> files;
    LS(testDir, files);
    
    // 应该至少包含两个文件
    ASSERT_TRUE(files.size() >= 2);
    
    test_common::cleanupTestDir(testDir);
}

void test_getName()
{
    std::string filePath = "/path/to/test_file.txt";
    std::string name;
    GET_NAME(filePath, name);
    ASSERT_STREQ("test_file", name.c_str());
    
    filePath = "/path/to/test.file.tar.gz";
    GET_NAME(filePath, name);
    ASSERT_STREQ("test", name.c_str());
    
    filePath = "simple";
    GET_NAME(filePath, name);
    ASSERT_STREQ("simple", name.c_str());
}

void test_shCmd()
{
    std::string result;
    bool ret = BASH("echo 'test output'", result);
    ASSERT_TRUE(ret);
    // 结果可能包含换行符，所以检查是否包含内容
    ASSERT_TRUE(result.find("test output") != std::string::npos);
}

int main()
{
    auto& runner = test_common::TestRunner::getInstance();
    runner.reset();
    
    std::cout << "=== Running Bash Module Tests ===" << std::endl;
    
    runner.runTest("test_mkDir", test_mkDir);
    runner.runTest("test_rmDir", test_rmDir);
    runner.runTest("test_touch", test_touch);
    runner.runTest("test_cpFile", test_cpFile);
    runner.runTest("test_mvFile", test_mvFile);
    runner.runTest("test_rmFile", test_rmFile);
    runner.runTest("test_list", test_list);
    runner.runTest("test_getName", test_getName);
    runner.runTest("test_shCmd", test_shCmd);
    
    std::cout << "\n=== Test Results ===" << std::endl;
    std::cout << "Total: " << runner.getTotal() << std::endl;
    std::cout << "Passed: " << runner.getPassed() << std::endl;
    std::cout << "Failed: " << runner.getFailed() << std::endl;
    
    return runner.getFailed() == 0 ? 0 : 1;
}

